<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>聊天</title>
    <!-- import Vue before Element -->
    <script src="https://unpkg.com/vue@2/dist/vue.js"></script>
    <!-- import JavaScript -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <!-- 引入Axios -->
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<style>
    .message {
        padding: 10px;
        margin: 5px 0;
        border-radius: 5px;
        max-width: 70%;
        /*display: inline-block;*/
        word-wrap: break-word;
        clear: both;
    }

    .me {
        float: right;
        background-color: #409EFF;
        color: white;
    }

    .not-me {
        float: left;
        background-color: #E9EEF3;
        color: black;
    }
</style>
<body>
<div id="app">
    <h3>基于 sse 实现对话&通知 案例 @散装java</h3>
    <el-container style="height: 600px; border: 1px solid #eee ;width: 75%">
        <el-main>
            <!--  系统公告-->
            <div v-for="(message, index) in notices">
                <el-alert
                        :title="'系统公告: ' + message"
                        type="info"
                        close-text="知道了">
                </el-alert>
            </div>

            <!-- 聊天记录区域 -->
            <div v-for="(message, index) in messages" :key="index" class="message"
                 :class="{ me: message.isMe, not_me: !message.isMe }">
                <div>{{ message.text }}</div>
            </div>
        </el-main>
        <el-footer>
            <el-row>
                <el-col :span="20" align="middle">
                    <el-input v-model="newMessage" placeholder="输入消息" @keydown.enter.native="sendMessage"></el-input>

                </el-col>
                <el-col :span="4" align="middle">
                    <el-button @click="sendMessage" type="primary">发送</el-button>
                </el-col>
            </el-row>
        </el-footer>
    </el-container>
</div>

</body>

<script>
    new Vue({
        el: '#app',
        data() {
            return {
                messages: [
                    {text: '你好！', isMe: false},
                    {text: '你好，很高兴见到你。', isMe: true}
                ],
                notices: [],
                newMessage: ''
            };
        },
        mounted() {
            this.startSSE();
        },
        methods: {
            sendMessage() {
                if (this.newMessage.trim()) {
                    this.messages.push({text: this.newMessage, isMe: true});
                    this.sendMsgSse(this.newMessage)
                    this.newMessage = ''; // 清空输入框
                }
                // 请求后台接口
            },

            startSSE() {
                const eventSource = new EventSource('http://localhost:8080/sse/createConnect?loginId=666&clientId=2&setHeartBeat=false');

                eventSource.onmessage = (event) => {
                    console.log("后台传来消息", event);
                    // 讲后台返回的内容添加到公告区域展示
                    const data = JSON.parse(event.data);
                    this.notices.push(data.data)
                };

                eventSource.onerror = (event) => {
                    console.error('EventSource failed: ', event);
                    eventSource.close(); // 可以选择在发生错误时关闭连接
                };

                eventSource.addEventListener('end', (event) => {
                    console.log('Server closed the connection: ', event);
                    eventSource.close();
                });
            },

            sendMsgSse(content) {
                fetch('http://localhost:8080/sse/chat', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({
                        'content': content,
                        'loginId': 666,
                        'clientId': 1
                    })
                })
                    .then(async response => {
                        const reader = response.body.getReader();
                        let buffer = '';
                        let result = {
                            text: '',
                            isMe: false
                        };
                        this.messages.push(result)

                        reader.read().then(function process({done, value}) {
                            console.log("done,value", done, value)
                            if (done) {
                                console.log('Stream closed', buffer);
                                return;
                            }
                            buffer += new TextDecoder('utf-8').decode(value);
                            const lines = buffer.split('\n');
                            buffer = lines.pop();
                            lines.forEach(line => {
                                console.log("内容:" + line);
                                if (line.startsWith('data:')) {
                                    result.text += JSON.parse(line.substring(5)).data;
                                }
                            });

                            // Continue reading
                            return reader.read().then(process);
                        })

                    })
                    .catch(error => {
                        console.error('Error:', error);
                    });
            }
        }
    });
</script>
</html>